package com.zt.bigdata.vertx.service

import java.util.Objects

import com.ecfront.dew.common.Resp
import com.typesafe.scalalogging.LazyLogging
import com.zt.bigdata.vertx.ResponseContent
import com.zt.bigdata.vertx.interceptor._
import io.vertx.core.Handler
import io.vertx.core.http.HttpServerResponse
import io.vertx.ext.web.RoutingContext
import javax.annotation.PostConstruct
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.{MediaType, ResponseEntity}
import org.springframework.stereotype.Service

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Promise

/**
  *
  */
@Service
class BasicHandler[E <: Animal, R <: Object] @Autowired()
(aFilter: AFilter[E, R], bFilter: BFilter[E, R], asyncHttpFilterProcessor: AsyncHttpFilterProcessor[E, R])
  extends LazyLogging {

  def handleResponseEntity(response: HttpServerResponse, result: ResponseEntity[Object]): Unit = {
    val r = if (result == null)
      ResponseEntity.ok("")
    else
      result
    val headers = r.getHeaders
    val contentType = headers.getContentType
    resp(r.getStatusCodeValue, r.getBody, contentType, response)
  }

  def resp(httpCode: Int, res: Object, mediaType: MediaType, response: HttpServerResponse): Unit = {
    logger.trace("Response [{}] : {}", httpCode, res)
    val contentType = if (mediaType == null)
      MediaType.TEXT_HTML_VALUE
    else
      mediaType.toString
    response.setStatusCode(httpCode)
      .putHeader("Content-Type", contentType)
      .putHeader("Cache-Control", "no-cache")
      .putHeader("Access-Control-Allow-Origin", "*")
      .putHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
      .putHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With, X-client," + ResponseContent.FLAG_AUTHORIZATION + "," + ResponseContent.FLAG_PROXY)
      .end(Objects.toString(res, ""))
  }

  @PostConstruct def init(): Unit = {
    asyncHttpFilterProcessor.register(getFilterGroup, getFilters: _*)
  }

  def getFilterGroup: String = "default-collect"

  def getFilters: Seq[HttpAsyncFilter[E, R]] = Seq()

  def toHandler(processFunction: ProcessFunction[E, R])(implicit r: Manifest[R]): Handler[RoutingContext] = new Handler[RoutingContext] {
    override def handle(routingContext: RoutingContext): Unit = {
      val request = routingContext.request()
      val pathParam = request.getParam("name");

      val animal = Dog()

      request.exceptionHandler(new Handler[Throwable] {
        override def handle(e: Throwable): Unit = {
          handleException(request.response(), e)
        }
      })

      val future = Promise[Resp[R]]
      asyncHttpFilterProcessor.process(getFilterGroup, animal.asInstanceOf[E], processFunction, routingContext).onSuccess {
        case resp => if (resp.ok()) {
          future.success(Resp.success("ok".asInstanceOf[R]))
        } else {
          future.success(Resp.badRequest("not ok"));
        }
      }

      future.future.onSuccess {
        case resp => if (resp.ok())
          routingContext.request.response.setStatusCode(200).end("OK")
        else
          routingContext.request.response.setStatusCode(405).end("Method Not Allowed")
      }
    }
  }

  def handleException(response: HttpServerResponse, throwable: Throwable): Unit = {
    logger.error("request Process Error", throwable)
    resp(500, throwable.getMessage, MediaType.TEXT_HTML, response)
  }
}
